package states
{
	import flash.display.Stage;
	import flash.events.Event;
	import flash.system.fscommand;
	import flash.text.TextField;
	import states.*;
	import utilities.KeyboardInputManager;
	
	/**
	 * ...
	 * @author Leong Shi Yun
	 */
	public class GameStateManager
	{
		/* public const/var */
		// colours for easier debugging purposes
		public static const uiGSM_QUIT:uint					= 0;
		public static const uiGSM_RESTART:uint				= 1;
		
		public static const uiGSM_MAINMENU:uint				= 2;
		public static const uiGSM_GAMEPLAY:uint				= 3;
		public static const uiGSM_REPLAYMENU:uint			= 4;
		
		/* private variables/consts */
		private var m_stage:Stage = null;
		private var m_state:IState = null;
		
		private static var m_uiPrevState:uint = 0;
		private static var m_uiCurrState:uint = 0;
		private static var m_uiNextState:uint = 0;
		
		/* public functions */
		/**
		 * Creates a new instance of the game state manager
		 */
		public function GameStateManager()
		{
			
		}
		
		/**
		 * Initalizes the game state manager. It takes in the stage from the Main.
		 * This stage will be used later to add the graphics from the level states.
		 *
		 * The reason why the initalize is seperated from the constructor is
		 * because while the constructor can only be called once, while this function can be called numerous times.
		 * This is especially essential when it comes to uninitalizing and destroying stuff.
		 *
		 * @param	stage is the stage parsed in from the Main
		 */
		public function initialize(stage:Stage):void
		{
			/*m_state = new MainMenu() as MainMenu;
			m_uiPrevState = m_uiCurrState = m_uiNextState = uiGSM_MAINMENU;*/
			m_state = new Gameplay() as Gameplay;
			m_uiPrevState = m_uiCurrState = m_uiNextState = uiGSM_GAMEPLAY;
			
			m_stage = stage;
			m_state.initialize(m_stage);
		}
		
		/**
		 * The Update is responsible for keeping track of the current values of the previous,
		 * current and the next states.
		 *
		 * It checks the current state against certain values:
		 * 		if the current state is quit, quit the current level
		 *
		 * 		if the current state is restart
		 * 			uinitialize and initialize the current state and
		 * 			switch the next state back to the previous state
		 *
		 * 		if the current state is the same as the next state
		 * 			keep undating the current state's behaviour
		 *
		 * 		if the current state and the next state do not match,
		 * 			set the previous state to the current state
		 * 			and the current state to the next state.
		 */
		public function update():void
		{
			if (m_uiCurrState == uiGSM_QUIT)
			{
				if (m_state)
				{
					m_state.destroy();
				}
			}
			else if (m_uiCurrState == uiGSM_RESTART)
			{
				if (m_state)
				{
					m_state.uninitialize();
					m_state.initialize(m_stage);
					m_uiNextState = m_uiPrevState;
					m_uiCurrState = m_uiNextState;
				}
			}
			else if (m_uiCurrState == m_uiNextState)
			{
				if (m_state)
				{
					m_state.update();
				}
			}
			else
			{
				m_uiPrevState = m_uiCurrState;
				m_uiCurrState = m_uiNextState;
				
				if (m_state)
				{
					m_state.destroy();
				}
				
				switchToState();
			}
		}
		
		/**
		 * Destroys the game state manager
		 */
		public function destroy():void
		{
			m_stage = null;
			m_state = null;
		}//end Destroy
		
		/**
		 * Gets the name of the state. This is more to aid in debugging and it more user-friendly.
		 * It's easier to debug with strings than with numbers.
		 *
		 * @param	uiState:uint the state to be checked.
		 * @return	the name of the state as an unsigned integer.
		 */
		public static function getStateName(uiState:uint):String
		{
			switch(uiState)
			{
				case uiGSM_QUIT:
					return "Quit";
					break;
					
				case uiGSM_RESTART:
					return "Restart";
					break;
					
				case uiGSM_MAINMENU:
					return "MainMenu";
					break;
					
				case uiGSM_GAMEPLAY:
					return "Gameplay";
					break;
					
				case uiGSM_REPLAYMENU:
					return "ReplayMenu";
					break;
					
				default:
					return "State does not exist!";
					break;
			}
			
			return "";
		}
		
		/**
		 * Gets the current value of the previous state
		 */
		public static function get previousState():uint
		{
			return m_uiPrevState;
		}
		
		/**
		 * Gets the current value of the current state
		 */
		public static function get currentState():uint
		{
			return m_uiCurrState;
		}
		
		/**
		 * Gets tthe current value of the next state
		 */
		public static function get nextState():uint
		{
			return m_uiNextState;
		}
		
		/**
		 * Sets a new state for the next state.
		 */
		public static function set nextState(sState:uint):void
		{
			m_uiNextState = sState;
		}
		
		/* private functions */
		/**
		 * Checks for the value of the currState and switches and initializes the new state.
		 */
		private function switchToState():void
		{
			switch(m_uiCurrState)
			{
				case uiGSM_MAINMENU:
					m_state = new MainMenu() as MainMenu;
					m_state.initialize(m_stage);
					break;

				case uiGSM_GAMEPLAY:
					m_state = new Gameplay() as Gameplay;
					m_state.initialize(m_stage);
					break;
				
				case uiGSM_REPLAYMENU:
					m_state = new ReplayMenu() as ReplayMenu;
					m_state.initialize(m_stage);
					break;
					
				default:
					break;
			}
			
		}
		
	}

}
